﻿using System;
using System.Globalization;
using System.Reflection;

namespace UnitDriven
{
	[System.Diagnostics.DebuggerNonUserCode]
	public static class Assert
	{
		public static void AreEqual(object expected, object actual)
		{
			AreEqual(expected, actual, Properties.Resources.AssertAreEqualFailed);
		}

		public static void AreEqual(object expected, object actual, string message, params object[] args)
		{
			if (!object.Equals(expected, actual))
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void AreNotEqual(object expected, object actual)
		{
			AreNotEqual(expected, actual,  Properties.Resources.AssertAreNotEqualFailed);
		}
		public static void AreNotEqual(object expected, object actual, string message, params object[] args)
		{
			if (object.Equals(expected, actual))
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void IsNull(object actual)
		{
			IsNull(actual,  Properties.Resources.AssertIsNullFailed);
		}
		public static void IsNull(object actual, string message, params object[] args)
		{
			if (actual != null)
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void IsNotNull(object actual)
		{
			IsNotNull(actual,  Properties.Resources.AssertIsNotNullFailed);
		}
		public static void IsNotNull(object actual, string message, params object[] args)
		{
			if (actual == null)
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void AreSame(object expected, object actual)
		{
			AreSame(expected, actual,  Properties.Resources.AssertAreSameFailed);
		}
		public static void AreSame(object expected, object actual, string message, params object[] args)
		{
			if (!object.ReferenceEquals(expected, actual))
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void AreNotSame(object expected, object actual)
		{
			AreNotSame(expected, actual,  Properties.Resources.AssertAreNotSameFailed);
		}
		public static void AreNotSame(object expected, object actual, string message, params object[] args)
		{
			if (object.ReferenceEquals(expected, actual))
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void IsTrue(bool value)
		{
            IsTrue(value, Properties.Resources.AssertIsTrueFailed);
		}
		public static void IsTrue(bool value, string message, params object[] args)
		{
			if (!value)
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void IsFalse(bool value)
		{
            IsFalse(value, Properties.Resources.AssertIsFalseFailed);
		}
		public static void IsFalse(bool value, string message, params object[] args)
		{
			if (value)
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void Fail()
		{
            throw new TestException(Properties.Resources.AssertFail);
		}

		public static void Fail(string message, params object[] args)
		{
			throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void IsInstanceOfType(Type expected, object actual)
		{
            IsInstanceOfType(expected, actual, Properties.Resources.AssertIsInstanceOfTypeFailed);
		}

		public static void IsInstanceOfType(Type expected, object actual, string message, params object[] args)
		{
			if (expected == null)
				throw new ArgumentNullException("expected");

			if (actual == null)
				throw new ArgumentNullException("actual");

#if NETFX_CORE
            if (!expected.GetTypeInfo().IsAssignableFrom(actual.GetType().GetTypeInfo()))
#else
			if (!expected.IsAssignableFrom(actual.GetType()))
#endif
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void IsNotInstanceOfType(Type expected, object actual)
		{
            IsNotInstanceOfType(expected, actual, Properties.Resources.AssertIsNotInstanceOfTypeFailed);
		}

		public static void IsNotInstanceOfType(Type expected, object actual, string message, params object[] args)
		{
			if (expected == null)
				throw new ArgumentNullException("expected");

			if (actual == null)
				throw new ArgumentNullException("actual");

#if NETFX_CORE
            if (expected.GetTypeInfo().IsAssignableFrom(actual.GetType().GetTypeInfo()))
#else
			if (expected.IsAssignableFrom(actual.GetType()))
#endif
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void IsNotEmpty(string value, string message, params object[] args)
		{
			if (object.Equals(value, string.Empty))
				throw new TestException(string.Format(CultureInfo.CurrentCulture, message, args));
		}

		public static void IsNotEmpty(string value)
		{
            IsNotEmpty(value, string.Empty, Properties.Resources.AssertIsNotEmptyFailed);
		}
	}
}
